// AC自动机模版(优化版)
// 给你若干目标字符串，还有一篇文章
// 返回每个目标字符串在文章中出现了几次
// 测试链接 : https://www.luogu.com.cn/problem/P5357
// 提交以下的code，可以直接通过

#include <bits/stdc++.h>

using namespace std;

// 目标字符串的数量
const int MAXN = 200001;
// 所有目标字符串的总字符数量
const int MAXS = 2000001;
char s[MAXS];
// 记录每个目标串的结尾节点编号
int end[MAXN];
// AC自动机
int tree[MAXS][26];
int fail[MAXS];
int cnt = 0;
// 具体题目相关，本题为收集词频
// 所以每个节点记录词频
int times[MAXS];
// 可以用作队列或者栈，一个容器而已
int box[MAXS];
// 链式前向星，为了建立fail指针的反图
int head[MAXS];
int next[MAXS];
int to[MAXS];
int edge = 0;
// 遍历fail反图，递归方法会爆栈，所以用非递归替代
bool visited[MAXS];

inline int read()
{
    char ch = getchar();
    int x = 0, f = 1;
    while(ch < '0' || ch > '9')
    {
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = 10 * x + ch - '0';
        ch = getchar();
    }
    return f * x;
}

void addEdge(int u, int v)
{
    ::next[++edge] = head[u];
    head[u] = edge;
    to[edge] = v;
}

// AC自动机加入目标字符串
void insert(int i, char* str)
{
    int u = 0, n = strlen(str);
    for(int j = 0, ch; j < n; ++j)
    {
        ch = str[j] - 'a';
        if(tree[u][ch] == 0) tree[u][ch] = ++cnt;
        u = tree[u][ch];
    }
    // 每个目标字符串的结尾节点编号
    ::end[i] = u;
}

// 加入所有目标字符串之后
// 设置fail指针 以及 设置直接直通表
// 做了AC自动机固定的优化
void setFail()
{
    // box当做队列来使用
    int l = 0, r = 0;
    for(int i = 0; i <= 25; ++i)
    {
        if(tree[0][i]) box[r++] = tree[0][i];
    }
    while(l < r)
    {
        int u = box[l++];
        for(int i = 0; i <= 25; ++i)
        {
            if(tree[u][i] == 0)
            {
                tree[u][i] = tree[fail[u]][i];
            }
            else
            {
                fail[tree[u][i]] = tree[fail[u]][i];
                box[r++] = tree[u][i];
            }
        }
    }
}

// 逻辑是对的
// 但是递归开太多层了会爆栈
// C++这道题不会爆栈
// java会
void f1(int u)
{
    for(int ei = head[u]; ei > 0; ei = ::next[ei])
    {
        f1(to[ei]);
        times[u] += times[to[ei]];
    }
}

// 改成非递归才能通过
// 因为是用栈来模拟递归
// 只消耗内存空间(box和visited)
// 不消耗系统栈的空间
// 所以很安全
void f2(int u)
{
    // box当做栈来使用
    int r = 0;
    box[r++] = u;
    while(r > 0)
    {
        int cur = box[r - 1];
        if(!visited[cur])
        {
            visited[cur] = true;
            for(int ei = head[cur]; ei > 0; ei = ::next[ei])
            {
                box[r++] = to[ei];
            }
        }
        else
        {
            --r;
            for(int ei = head[cur]; ei > 0; ei = ::next[ei])
            {
                times[cur] += times[to[ei]];
            }
        }
    }
}

int main()
{
    int n = read();
    // AC自动机建树
    for(int i = 1; i <= n; ++i)
    {
        scanf("%s", s);
        insert(i, s);
    }
    setFail();
    // 读入大文章
    scanf("%s", s);
    int len = strlen(s);
    for(int u = 0, i = 0; i < len; ++i)
    {
        u = tree[u][s[i] - 'a'];
        // 增加匹配次数
        ++times[u];
    }
    for(int i = 1; i <= cnt; ++i)
    {
        // 根据fail指针建反图
        // 其实是一颗树
        addEdge(fail[i], i);
    }
    // 遍历fail指针建的树
    // 汇总每个节点的词频
    f1(0);
    for(int i = 1; i <= n; ++i) printf("%d\n", times[::end[i]]);

    return 0;
}